home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / TERMINAL / SRCS / MACBINAR.C < prev    next >
Text File  |  1990-11-20  |  13KB  |  545 lines

  1. /*
  2.     Terminal 2.0
  3.     "MacBinary.c"
  4. */
  5.  
  6. #ifdef THINK_C
  7. #include "MacHeaders"
  8. #endif
  9. #ifdef applec
  10. #pragma load ":(Objects):MacHeadersMPW"
  11. #pragma segment Main2
  12. #endif
  13.  
  14. #include "MacBinary.h"
  15. #include "CRC.h"
  16. #include "Utilities.h"
  17.  
  18. typedef struct {
  19.     Byte oldVersion;        /* 000: Must be zero for compatibility */
  20.     Byte name[64];            /* 001: Pascal string */
  21.     Byte info1[16];            /* 065: Original Finder info: */
  22.                             /*        File type (long) */
  23.                             /*        File creator (long) */
  24.                             /*        Flags (word, low byte must be zero) */
  25.                             /*        File's location (Point) */
  26.                             /*        File's window (short) */
  27.     Byte protected;            /* 081: Low order bit */
  28.     Byte zero1;                /* 082: Must be zero for compatibility */
  29.     Byte dLength[4];        /* 083: Data fork length (in bytes) */
  30.     Byte rLength[4];        /* 087: Resource fork length (in bytes) */
  31.     Byte creation[4];        /* 091: Creation date */
  32.     Byte modification[4];    /* 095: Modification date */
  33.     Byte getInfoLength[2];    /* 099:    Get info length */
  34.     Byte info2;                /* 101: Finder flags, low byte */
  35.     Byte zero2[14];            /* 102: Not used */
  36.     Byte filesLength[4];    /* 116: Length of total unpacked files */
  37.     Byte sHeaderLength[2];    /* 120: Length of secondary header */
  38.     Byte newVersion;        /* 122: Uploading program version number */
  39.     Byte minimumVersion;    /* 123: Minimum version number needed */
  40.     Byte crc[2];            /* 124: CRC of previous 124 bytes */
  41.     Byte zero3[2];            /* 126: Not used */
  42. } HEADER;
  43.  
  44. #define DESKTOP        0x0001    /* ---- ---- ---- ---1 */
  45. #define    COLOR        0x000E    /* ---- ---- ---- 111- */
  46. #define INITED        0x0100    /* ---- ---1 ---- ---- */
  47. #define CHANGED        0x0200    /* ---- --1- ---- ---- */
  48. #define BUSY        0x0400    /* ---- -1-- ---- ---- */
  49. #define BOZO        0x0800    /* ---- 1--- ---- ---- */
  50. #define SYSTEM        0x1000    /* ---1 ---- ---- ---- */
  51. #define BUNDLE        0x2000    /* --1- ---- ---- ---- */
  52. #define INVISIBLE    0x4000    /* -1-- ---- ---- ---- */
  53. #define LOCKED        0x8000    /* 1--- ---- ---- ---- */
  54.  
  55. #define NOMODIFY    (DESKTOP | INITED | CHANGED | BUSY)
  56.  
  57. typedef struct {
  58.     Byte            name[64];    /* File name */
  59.     short            volume;        /* Volume reference number */
  60.     long            directory;    /* Directory ID */
  61.     short            ref;        /* File reference number */
  62.     long            data;        /* Size of data fork */
  63.     long            resource;    /* Size of resource fork */
  64.     long            mark;        /* Current read/write mark */
  65.     HEADER header;                /* MacBinary header */
  66. } MBFCB;
  67.  
  68. static MBFCB **File = 0;        /* Current file control block handle */
  69.  
  70. /* ----- Minimum ------------------------------------------------------- */
  71.  
  72. static long Minimum(register long a, register long b)
  73. {
  74.     return (a < b) ? a : b;
  75. }
  76.  
  77. /* ----- Set up MacBinary header --------------------------------------- */
  78.  
  79. static short InitMacBinary(
  80.     short volume,
  81.     long directory,
  82.     Byte *name,
  83.     HEADER *header,
  84.     long *data,
  85.     long *resource)
  86. {
  87.     register short err;
  88.     register Byte *p;
  89.     unsigned short crc;
  90.     HFileParam param;
  91.  
  92.     memset(¶m, 0, sizeof(param));
  93.     param.ioNamePtr = (StringPtr)name;
  94.     param.ioVRefNum = volume;
  95.     param.ioDirID = directory;
  96.     if (err = PBHGetFInfo((HParmBlkPtr)¶m, FALSE))
  97.         return err;
  98.  
  99.     p = (Byte *)header + sizeof(HEADER);
  100.     do
  101.         *(--p) = 0;
  102.     while (p > (Byte *)header);
  103.  
  104.     memcpy(header->name, name, name[0] + 1);
  105.     header->info2 = param.ioFlFndrInfo.fdFlags & 0x00FF;
  106.     param.ioFlFndrInfo.fdFlags &= 0xFF00;
  107.     *(long *)¶m.ioFlFndrInfo.fdLocation = 0;
  108.     param.ioFlFndrInfo.fdFldr = 0;
  109.     memcpy((void *)header->info1, (void *)¶m.ioFlFndrInfo,
  110.         sizeof(header->info1));
  111.     header->protected = (Byte)(param.ioFlAttrib) & 0x01;
  112.     memcpy((void *)header->dLength, (void *)¶m.ioFlLgLen, 4);
  113.     memcpy((void *)header->rLength, (void *)¶m.ioFlRLgLen, 4);
  114.     memcpy((void *)header->creation, (void *)¶m.ioFlCrDat, 4);
  115.     memcpy((void *)header->modification, (void *)¶m.ioFlMdDat, 4);
  116.     header->newVersion = 129;
  117.     header->minimumVersion = 129;
  118.     crc = CalcCRC((Byte *)header, 124, 0);
  119.     memcpy((void *)header->crc, (void *)&crc, 2);
  120.  
  121.     *data = param.ioFlLgLen;
  122.     *resource = param.ioFlRLgLen;
  123.     return 0;
  124. }
  125.  
  126. /* ----- Verify MacBinary header --------------------------------------- */
  127.  
  128. short BinCheckHeader(
  129.     register Byte *p,
  130.     Byte *name,                /* File name */
  131.     long *data,                /* Data fork length */
  132.     long *resource)            /* Resource fork length */
  133. {
  134.     register short i, j, version;
  135.     register HEADER *header;
  136.     unsigned short crc;
  137.  
  138.     *name = 0;
  139.     *data = *resource = 0;
  140.     header = (HEADER *)p;
  141.     if (p[0] || p[74] || p[82] || p[83] || p[87] ||
  142.             (i = header->name[0]) > 63)
  143.         return 0;
  144.     memcpy((void *)&crc, (void *)header->crc, 2);
  145.     if (crc == CalcCRC((Byte *)header, 124, 0) &&
  146.             header->minimumVersion <= 129)
  147.         version = 2;
  148.     else {
  149.         for (j = 101; j < 125; j++)
  150.             if (p[j])
  151.                 return 0;
  152.         version = 1;
  153.     }
  154.     memcpy((void *)name, (void *)header->name, i + 1);
  155.     memcpy((void *)data, (void *)header->dLength, 4);
  156.     memcpy((void *)resource, (void *)header->rLength, 4);
  157.     return version;
  158. }
  159.  
  160. /* ----- Set up file info from MacBinary header ------------------------ */
  161.  
  162. static short SetupMacBinary(
  163.     HEADER *header,
  164.     short volume,
  165.     long directory,
  166.     Byte *name)
  167. {
  168.     register short err;
  169.     HFileParam param;
  170.     FInfo info;
  171.  
  172.     memset(¶m, 0, sizeof(param));
  173.     param.ioNamePtr = (StringPtr)name;
  174.     param.ioVRefNum = volume;
  175.     param.ioDirID = directory;
  176.     if (err = PBHGetFInfo((HParmBlkPtr)¶m, FALSE))
  177.         return err;
  178.  
  179.     memcpy((void *)&info, (void *)header->info1, sizeof(info));
  180.     info.fdFlags &= 0xFF00;            /* High byte */
  181.     info.fdFlags |= header->info2;    /* Low byte */
  182.     info.fdFlags &= ~NOMODIFY;
  183.     param.ioFlFndrInfo.fdType = info.fdType;
  184.     param.ioFlFndrInfo.fdCreator = info.fdCreator;
  185.     param.ioFlFndrInfo.fdFlags &= NOMODIFY;
  186.     param.ioFlFndrInfo.fdFlags |= info.fdFlags;
  187.     memcpy((void *)¶m.ioFlCrDat, (void *)header->creation, 4);
  188.     memcpy((void *)¶m.ioFlMdDat, (void *)header->modification, 4);
  189.     param.ioNamePtr = (StringPtr)name;
  190.     param.ioVRefNum = volume;
  191.     param.ioDirID = directory;
  192.     return PBHSetFInfo((HParmBlkPtr)¶m, FALSE);
  193. }
  194.  
  195. /* ----- Open disk file for reading ------------------------------------ */
  196.  
  197. short BinOpenRead(
  198.     register short volume,
  199.     register long directory,
  200.     register Byte *name)
  201. {
  202.     register MBFCB **f;
  203.     register MBFCB *p;
  204.     register short err;
  205.  
  206.     if (File)
  207.         return 1;        /* Is already open! */
  208.     if (!(f = (MBFCB **)NewHandle(sizeof(MBFCB))))
  209.         return 2;        /* Memory problem! */
  210.  
  211.     HLock((Handle)f);
  212.     p = *f;
  213.     if (!(err = InitMacBinary(volume, directory, name,
  214.             &p->header, &p->data, &p->resource))) {
  215.         memcpy((void *)p->name, (void *)name, name[0] + 1);
  216.         p->volume = volume;
  217.         p->directory = directory;
  218.         p->mark = 0;
  219.     }
  220.     HUnlock((Handle)f);
  221.     if (err)
  222.         DisposHandle((Handle)f);
  223.     else
  224.         File = f;        /* Now is open */
  225.     return err;
  226. }
  227.  
  228. /* ----- Read from disk file ------------------------------------------- */
  229.  
  230. short BinRead(
  231.     long *count,
  232.     Byte *buffer)
  233. {
  234.     register MBFCB **f;
  235.     register MBFCB *p;
  236.     register short err;
  237.     register long n;
  238.     long b, c, d, e;
  239.     long i;
  240.  
  241.     if (!(f = File))
  242.         return 1;        /* Is not open! */
  243.     HLock((Handle)f);
  244.     p = *f;
  245.  
  246.     b = sizeof(HEADER) + p->data;
  247.     c = b + Filler(BinHeaderLength, p->data);
  248.     d = c + p->resource;
  249.     e = d + Filler(BinHeaderLength, p->resource);
  250.  
  251.     /* Open data fork of file if necessary */
  252.  
  253.     if (p->mark == sizeof(HEADER) &&
  254.             (err = OpenFile(p->volume,p->directory,p->name,&p->ref)))
  255.         goto done;
  256.  
  257.     /* Close data fork of file if necessary */
  258.  
  259.     if (p->mark == b) {
  260.         FSClose(p->ref);
  261.         p->ref = 0;
  262.     }
  263.  
  264.     /* Open resource fork of file if necessary */
  265.  
  266.     if (p->mark == c &&
  267.             (err = OpenResource(p->volume,p->directory,p->name,&p->ref)))
  268.         goto done;
  269.  
  270.     /* Close resource fork of file if necessary */
  271.  
  272.     if (p->mark == d) {
  273.         FSClose(p->ref);
  274.         p->ref = 0;
  275.     }
  276.  
  277.     /* Copy from header */
  278.  
  279.     if (p->mark < sizeof(HEADER)) {
  280.         n = Minimum(*count, sizeof(HEADER) - p->mark);
  281.         memcpy((void *)buffer, (Byte *)&p->header + p->mark, n);
  282.         goto allright;
  283.     }
  284.  
  285.     /* Read data fork */
  286.  
  287.     if (p->mark < b) {
  288.         i = Minimum(*count, b - p->mark);
  289.         err = FSRead(p->ref, &i, buffer);
  290.         n = i;
  291.         goto done;
  292.     }
  293.  
  294.     /* Clear buffer (fill up to entire multiple of 128 bytes) */
  295.  
  296.     if (p->mark < c) {
  297.         n = Minimum(*count, c - p->mark);
  298.         memset(buffer, 0, n);
  299.         goto allright;
  300.     }
  301.  
  302.     /* Read resource fork */
  303.  
  304.     if (p->mark < d) {
  305.         i = Minimum(*count, d - p->mark);
  306.         err = FSRead(p->ref, &i, buffer);
  307.         n = i;
  308.         goto done;
  309.     }
  310.  
  311.     /* Clear buffer (fill up to entire multiple of 128 bytes) */
  312.  
  313.     if (p->mark < e) {
  314.         n = Minimum(*count, e - p->mark);
  315.         memset(buffer, 0, n);
  316.         goto allright;
  317.     }
  318.  
  319.     /* End of file reached */
  320.  
  321.     err = eofErr;
  322.     n = 0;
  323.     goto done;
  324.  
  325. allright:
  326.     err = 0;        /* No error */
  327. done:
  328.     if (!err) {
  329.         p->mark += n;
  330.         if (c = *count - n)
  331.             err = BinRead(&c, buffer + n);
  332.         *count = n + c;
  333.     } else {
  334.         if (err == eofErr) {
  335.             p->mark += n;
  336.             *count = n;
  337.         }
  338.     }
  339.  
  340.     HUnlock((Handle)f);
  341.     return err;
  342. }
  343.  
  344. /* ----- Close disk file after reading --------------------------------- */
  345.  
  346. short BinCloseRead(void)
  347. {
  348.     register short ref;
  349.  
  350.     if (!File)
  351.         return 1;                /* Is not open! */
  352.     if (ref = (**File).ref)
  353.         FSClose(ref);            /* Data or resource fork */
  354.     DisposHandle((Handle)File);
  355.     File = 0;                    /* Now file is closed */
  356.     return 0;
  357. }
  358.  
  359. /* ----- Open disk file for writing ------------------------------------ */
  360.  
  361. short BinOpenWrite(
  362.     register short volume,
  363.     register long directory,
  364.     register Byte *name,
  365.     register Byte *header)
  366. {
  367.     register MBFCB **f;
  368.     register MBFCB *p;
  369.     Byte name2[64];
  370.  
  371.     if (File)
  372.         return 1;        /* Is already open! */
  373.  
  374.     if (!(f = (MBFCB **)NewHandle(sizeof(MBFCB))))
  375.         return 2;        /* Memory problem! */
  376.  
  377.     HLock((Handle)f);
  378.     p = *f;
  379.  
  380.     BinCheckHeader(header, name2, &p->data, &p->resource);
  381.     memcpy((void *)&p->header, (void *)header, sizeof(HEADER));
  382.     memcpy((void *)p->name, (void *)name, name[0] + 1);
  383.     p->volume = volume;
  384.     p->directory = directory;
  385.     p->mark = sizeof(HEADER);
  386.  
  387.     HUnlock((Handle)f);
  388.     File = f;            /* Now is open */
  389.     return 0;
  390. }
  391.  
  392. /* ----- Write to disk file -------------------------------------------- */
  393.  
  394. short BinWrite(
  395.     long *count,
  396.     Byte *buffer)
  397. {
  398.     register MBFCB **f;
  399.     register MBFCB *p;
  400.     register short err;
  401.     register long n;
  402.     long b, c, d, e;
  403.     long i;
  404.  
  405.     if (!(f = File))
  406.         return 1;        /* Is not open! */
  407.     HLock((Handle)f);
  408.     p = *f;
  409.  
  410.     b = sizeof(HEADER) + p->data;
  411.     c = b + Filler(BinHeaderLength, p->data);
  412.     d = c + p->resource;
  413.     e = d + Filler(BinHeaderLength, p->resource);
  414.  
  415.     /* Open data fork of file if necessary */
  416.  
  417.     if (p->mark == sizeof(HEADER) &&
  418.             (err = OpenFile(p->volume,p->directory,p->name,&p->ref)))
  419.         goto done;
  420.  
  421.     /* Close data fork of file if necessary */
  422.  
  423.     if (p->mark == b) {
  424.         FSClose(p->ref);
  425.         p->ref = 0;
  426.     }
  427.  
  428.     /* Open resource fork of file if necessary */
  429.  
  430.     if (p->mark == c &&
  431.             (err = OpenResource(p->volume,p->directory,p->name,&p->ref)))
  432.         goto done;
  433.  
  434.     /* Close resource fork of file if necessary */
  435.  
  436.     if (p->mark == d) {
  437.         FSClose(p->ref);
  438.         p->ref = 0;
  439.     }
  440.  
  441.     /* Ignore header */
  442.  
  443.     if (p->mark < sizeof(HEADER)) {
  444.         n = Minimum(*count, sizeof(HEADER) - p->mark);
  445.         goto allright;
  446.     }
  447.  
  448.     /* Write data fork */
  449.  
  450.     if (p->mark < b) {
  451.         i = Minimum(*count, b - p->mark);
  452.         err = FSWrite(p->ref, &i, buffer);
  453.         n = i;
  454.         goto done;
  455.     }
  456.  
  457.     /* Ignore buffer (filled up to entire multiple of 128 bytes) */
  458.  
  459.     if (p->mark < c) {
  460.         n = Minimum(*count, c - p->mark);
  461.         goto allright;
  462.     }
  463.  
  464.     /* Write resource fork */
  465.  
  466.     if (p->mark < d) {
  467.         i = Minimum(*count, d - p->mark);
  468.         err = FSWrite(p->ref, &i, buffer);
  469.         n = i;
  470.         goto done;
  471.     }
  472.  
  473.     /* Ignore buffer (filled up to entire multiple of 128 bytes) */
  474.  
  475.     if (p->mark < e) {
  476.         n = Minimum(*count, e - p->mark);
  477.         goto allright;
  478.     }
  479.  
  480.     /* End of file reached (can happen if using XModem 1K) */
  481.  
  482.     err = eofErr;
  483.     n = 0;
  484.     goto done;
  485.  
  486. allright:
  487.     err = 0;        /* No error */
  488. done:
  489.     if (!err) {
  490.         p->mark += n;
  491.         if (c = *count - n)
  492.             err = BinWrite(&c, buffer + n);
  493.         *count = n + c;
  494.     } else {
  495.         if (err == eofErr) {
  496.             p->mark += n;
  497.             *count = n;
  498.             err = noErr;
  499.         }
  500.     }
  501.  
  502.     HUnlock((Handle)f);
  503.     return err;
  504. }
  505.  
  506. /* ----- Close disk file after writing --------------------------------- */
  507.  
  508. short BinCloseWrite(void)
  509. {
  510.     register short err;
  511.     register MBFCB **f;
  512.     register MBFCB *p;
  513.  
  514.     if (!(f = File))
  515.         return 1;                /* Is not open! */
  516.     HLock((Handle)f);
  517.     p = *f;
  518.     err = SetupMacBinary((HEADER *)&p->header, p->volume, p->directory,
  519.         p->name);
  520.     if (p->ref)
  521.         FSClose(p->ref);        /* Data or resource fork */
  522.     FlushVol(0, p->volume);
  523.     HUnlock((Handle)f);
  524.     DisposHandle((Handle)f);
  525.     File = 0;                    /* Now file is closed */
  526.     return err;
  527. }
  528.  
  529. /* ----- Get length of complete MacBinary file ------------------------- */
  530.  
  531. short BinGetEOF(register long *eof)
  532. {
  533.     register MBFCB **f;
  534.     register MBFCB *p;
  535.  
  536.     *eof = 0;
  537.     if (!(f = File))
  538.         return 1;                /* Is not open! */
  539.     p = *f;
  540.     *eof = BinHeaderLength +
  541.         p->data + Filler(BinHeaderLength, p->data) +
  542.         p->resource + Filler(BinHeaderLength, p->resource);
  543.     return 0;
  544. }
  545.